// 引入库
import store from '@/store'
import axios from 'axios'
import router from '@/router'
import { Message } from 'element-ui'

// 创建 axios 实例, 一个独立的对象, 用途跟原来的 axios 一样,
// 可以独立拥有自己的基准路径和各种拦截器配置

const service = axios.create({
  // 这里用到到是环境变量
  // 脚手架默认会在
  // 运行dev时将根目录 .env.development 里面的变量注入到 process.env 环境变量中
  // 如果运行 build 则是注入 .env.production
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

// 请求拦截器
service.interceptors.request.use(config => {
  // 请求拦截器可以拦截到当前正在发送的请求, 获取到的参数, 是当前发送请求的设定
  if (store.state.user.token) {
    const timeout = 1000 * 60 * 60 * 24
    const loginTime = localStorage.getItem('loginTime')
    if (Date.now() - loginTime > timeout) {
      // 主动介入 token 失效步骤二, 每次注入token之前校验是否超时
      store.dispatch('user/logout')
      router.push('/login')
      return Promise.reject(new Error('token 已超时(主动)'))
    }
    config.headers.Authorization = `Bearer ${store.state.user.token}`
  }

  return config
})

// 响应拦截器
// 响应拦截器可以接收两个参数, 都是函数
// 第一个是网络层面成功回调, 第二个是网络层面失败的回调
service.interceptors.response.use(res => {
  console.log('网络层面成功')
  // 哪怕网络请求响应成功, 还需要检查数据层面是否失败
  console.log(res)
  const { success, message } = res.data
  if (success) {
    console.log('数据层面也成功')
    // 处理成功回调, 完全成功, 将 res.data.data 嵌套解开
    // 直接返回最终数据即可
    return res.data.data
  } else {
    console.log('数据层面的失败')
    // 数据层面的失败, 其实应该指定当前正在执行的异步操作
    // 直接报错, 不能再继续往下执行才对, 要实现这个效果
    // 返回原生 Promise 对象的 reject 方法即可
    // 提醒用户的弹窗
    Message.error(message)
    return Promise.reject(new Error(message))
  }
}, err => {
  // 这个地方是网络层面失败的回调
  // 比如断网, 比如服务器崩溃, 不小心写错请求 url
  // 也可能是后台认为我们的token 已经失效也是会进来这里
  // 我们故意跟后端约定了一个 code 如果是 10002 就是 token 错误
  // 由于这里面处理的错误可能性太多不一定每个响应都有 response 属性
  if (err.response && err.response.data.code === 10002) {
    store.dispatch('user/logout')
    router.push('/login')
  }

  console.log('网络层面失败')
  console.dir(err)
  // 1. 提示用户出错了
  Message.error(err.message)
  // 2. 阻止当前正在执行的异步操作
  return Promise.reject(err)
})

// 暴露实例
export default service
